package com.sc.server.system.test.springTimer;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.sc.common.exception.BusinessRuntimeException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 指定时间段，间隔，执行任务
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class TimeTrigger implements Trigger {
    //时间段
    List<TimeRange> timeRanges=new ArrayList<>(8);
    //任务频率
    private  Long frequency;
    /**
     * false 表示第一次执行
     */
    private boolean flag=false;
    private Integer type;

    public TimeTrigger(List<TimeRange> timeRanges, Long frequency, Integer type, Date startTime) {
        this.timeRanges = timeRanges;
        this.frequency = frequency;
        this.type = type;
        this.startTime = startTime;
    }
    //开始时间
    private Date startTime;
    @Override
    public Date nextExecutionTime(TriggerContext triggerContext) {
        //获取当前时间分钟小时
        Date nextTime=null;
        if(type==1){
             nextTime = getNextTime1();
        }else {
            nextTime = getNextTime2();
        }
        flag=true;
        return nextTime;
    }

    /**
     * 周期采集时间处理方式
     * @return
     */
    private Date getNextTime1() {
         //立即执行
          Date date = new Date();
            if(startTime==null){
                return   runByFlag(date);
            }
           else {
                String time = DateUtil.format(date, "yyyy-MM-dd HH:mm");
                //当前时间大于设置时间，立即执行
                String format = DateUtil.format(startTime, "yyyy-MM-dd HH:mm");
                if(time.compareTo(format)<=-1){
                    return DateUtil.parse(format);
                }else if(time.compareTo(format)==0) {
                    return  runByFlag(date);
                }else {
                    //第一次执行，且当前时间大于开始时间，我们需要计算最近一次执行时间
                    if(flag==false){
                        long startTimes = DateUtil.parse(format).getTime();
                        long n = (System.currentTimeMillis() - startTimes) / frequency;
                        long mod=Math.floorMod((System.currentTimeMillis() - startTimes),frequency);
                        if(mod!=0){
                            n=n+1;
                        }
                        return new Date(startTimes+n*frequency);
                    }else {
                        return runByFlag(date);
                    }
                }
            }
    }

    /**
     * 定时采集时间处理方式
     * @return
     */
    private Date getNextTime2() {
        Date date = new Date();
        String format = DateUtil.format(date, "HH:mm");
        String startTime =null;
        String endTime=null;
        for (int i=0;i<timeRanges.size();i++) {
            TimeRange timeRange=timeRanges.get(i);
            startTime= timeRange.getStartTime();
            endTime=timeRange.getEndTime();
            if(startTime!=null && endTime!=null){
                 //当前时间大于或等于开始时间
                  if(format.compareTo(startTime)>=0){
                        //当前时间小于或等于结束时间
                        if(format.compareTo(endTime)<=0){
                            List<String> times = timeRange.getTimes();
                            for(int j=0;j<times.size();j++){
                                  String front=times.get(j);
                                    String after=null;
                                  if((j+1)<times.size()){
                                        after=times.get(j+1);
                                  }
                                  //等于
                                  if(format.compareTo(front)==0){
                                      //第一次执行,立即执行
                                      if(flag==false){
                                          return date;
                                     }
                                     //下一个时间点执行
                                     else {
                                          if(after!=null){
                                              return  replateLastHHmm(date,after);
                                          }else {

                                            return   nextTimeOrNextDat(i,timeRanges.size(),date);
                                          }

                                      }
                                  }
                                  //在front 和after 之间 ，after时间点执行
                                 else if(format.compareTo(front)>=1 && format.compareTo(after)<=-1){
                                      if(after!=null){
                                          return  replateLastHHmm(date,after);
                                      }
                                        return nextTimeOrNextDat(i,timeRanges.size(),date);
                                  }
                                  //format==after
                                  else if(format.compareTo(after)==0){
                                      if(!flag){
                                          return date;
                                      }
                                      //下一个时间点执行
                                      else {
                                         if((j+2)<times.size()){
                                               return replateLastHHmm(date,times.get(j+2));
                                         }else {
                                           return  nextTimeOrNextDat(i,timeRanges.size(),date);
                                         }

                                      }
                                  }
                              }
                        }else {
                            if(i==(timeRanges.size()-1)){
                                DateTime tomorrow = DateUtil.tomorrow();
                                return replateLastHHmm(tomorrow,timeRanges.get(0).getStartTime());
                            }
                           continue;
                        }
                  }else  {
                     //当前时间小于开始时间
                      return replateLastHHmm(date,startTime);
                  }
            }

        }
        throw new BusinessRuntimeException("时间设置异常");
    }

    /**
     * 如果当前时间大于结束时间，并且是最后一条设置明天执行
     * 否则的话，设置下一个开始时间执行
     * @param i
     * @param size
     * @param date
     * @return
     */
    private Date nextTimeOrNextDat(int i,Integer size,Date date) {
        // 如果当前时间大于结束时间，并且是最后一条设置明天执行
        if(i==(size-1)){
            DateTime tomorrow = DateUtil.tomorrow();
            return replateLastHHmm(tomorrow,timeRanges.get(0).getStartTime());
        }
        //否则的话，设置下一个开始时间执行
        return  replateLastHHmm(date,timeRanges.get(i+1).getStartTime());
    }

    /**
     * 替换后面分钟小时
     * @param date
     * @param startTime
     * @return
     */
    private Date replateLastHHmm(Date date, String  startTime) {
        String format = DateUtil.format(date, "yyyy-MM-dd HH:mm");
        return DateUtil.parse( format.substring(0,11)+startTime);
    }

    private Date runByFlag(Date date) {
        if(!flag){
            return date;
        }else {
            return new Date(System.currentTimeMillis()+frequency);
        }
    }
}
